﻿using System;
using System.Globalization;
using System.IO;
using System.Text;
using Resolve.Contracts;
using Resolve.FlagInfo;

namespace Resolve.Core
{
    /// <summary>
    /// 查找标志
    /// </summary>
    public class FlagFinderFromString : IFlagFinder
    {
        /// <summary>
        /// 文件路径或者字符串内容
        /// </summary>
        public string Source { private get; set; }

        /// <summary>
        /// 字符读取对象
        /// </summary>
        private StringReader _stringReader;

        /// <summary>
        /// 查找标志
        /// </summary>
        public FlagCodeInFile FindFlags()
        {
            InitStringReader();
            int iLast = -1;//上一个字符
            int iPosition = 0;//字符位置
            int iFlagStart = 0;//标志开始位置
            int iFlagEnd = 0;//标志结束位置
            bool bFindFlag = false;//是否找到标志
            bool bFindFlagInBody = false;//在语句体中
            bool bProperty = false;//属性
            bool bFunc = false;//方法
            bool bBody = false;//语句体
            bool bSure = false;//是否确定标志类型
            int iSmallLevel = 0;//小括号层次数
            int iBigLevel = 0;//大括号层次数
            bool bIntoDouble = false;//是否进入双引号 
            FlagCodeInFile flagCodeInFile = new FlagCodeInFile(1, Source, string.Empty);
            try
            {

                int iCurrent = ReadNext();
                FlagCode flagCode = new FlagCode();
                StringBuilder sb = new StringBuilder();
                while (iCurrent != -1)
                {
                    //找到标志
                    if (iCurrent == ResolveConfig.Flag && !bFindFlag && iSmallLevel == 0 && iBigLevel == 0)
                    {
                        bFindFlag = true;
                        bProperty = true;
                        iFlagStart = iPosition;
                    }
                    else if (iCurrent == ResolveConfig.Flag && iLast == ResolveConfig.Flag && bFindFlag && !bIntoDouble && iSmallLevel == 0 && iBigLevel == 0) //找到@@，标志无效
                    {
                        bFindFlag = false;
                        bProperty = false;
                        iFlagEnd = iPosition;
                        flagCode.Code = ((char)ResolveConfig.Flag).ToString(CultureInfo.InvariantCulture) + (char)iCurrent;
                        flagCode.Start = iFlagStart;
                        flagCode.End = iFlagEnd;
                        flagCode.FlagStyle = FlagStyle.FlagEscape;
                        flagCodeInFile.AddCode(flagCode);
                        flagCode = new FlagCode();
                        iFlagStart = 0;
                        iFlagEnd = 0;
                        sb.Remove(sb.Length - 1, 1);
                    }
                    //找到标志
                    if (bFindFlag)
                    {
                        sb.Append(((char)iCurrent).ToString(CultureInfo.InvariantCulture));
                        //属性处理
                        if (bProperty && bFunc == false && bBody == false)
                        {
                            switch (iCurrent)
                            {
                                case 40://(
                                    bProperty = false;
                                    bFunc = true;
                                    iSmallLevel = 1;
                                    break;
                                case 32://空格
                                    bSure = true;
                                    flagCode.FlagStyle = FlagStyle.Property;
                                    iFlagEnd = iPosition;//把空格也算进去
                                    sb.Remove(sb.Length - 1, 1); //去掉空格
                                    break;
                                default:
                                    if (iLast == 13 && iCurrent == 10) //回车
                                    {
                                        bSure = true;
                                        flagCode.FlagStyle = FlagStyle.Property;
                                        iFlagEnd = iPosition - 2;//回车不算进去
                                        sb.Remove(sb.Length - 2, 2); //去掉\r\n(回车)
                                    }
                                    else if (iCurrent == 123) //{
                                    {
                                        bProperty = false;
                                        bBody = true;
                                        iSmallLevel = 0;
                                        iBigLevel = 1;
                                    }
                                    break;
                            }
                        }
                        else if (!bProperty && bFunc) //方法处理
                        {
                            if (iCurrent == 34 && !bIntoDouble)//("
                            {
                                bIntoDouble = true;
                            }
                            else if (iCurrent == 34 && iLast != 92 && bIntoDouble)//\")
                            {
                                bIntoDouble = false;
                            }
                            else if (iCurrent == 40 && !bIntoDouble)//(
                            {
                                iSmallLevel++;
                            }
                            else if (iCurrent == 41 && !bIntoDouble)//)
                            {
                                iSmallLevel--;
                            }
                            else if (iCurrent == 123) //{
                            {
                                bFunc = false;
                                bBody = true;
                                bIntoDouble = false;
                                iBigLevel = 1;
                            }
                            else if (iCurrent == 32 && !bIntoDouble && iSmallLevel == 0)//空格
                            {
                                bSure = true;
                                flagCode.FlagStyle = FlagStyle.Func;
                                iFlagEnd = iPosition;//空格也算进去0
                                sb.Remove(sb.Length - 1, 1); //去掉空格
                            }
                            else if (iLast == 13 && iCurrent == 10) //回车
                            {
                                bSure = true;
                                if (flagCode.Code.StartsWith(((char)ResolveConfig.Flag) + "PlaceHolder(\""))
                                {
                                    flagCode.FlagStyle = FlagStyle.PlaceHolder;
                                }
                                else
                                {
                                    flagCode.FlagStyle = FlagStyle.Func;
                                }
                                iFlagEnd = iPosition - 2;//回车不算进去
                                sb.Remove(sb.Length - 2, 2); //去掉\r\n(回车)
                                iSmallLevel = 0;
                                bIntoDouble = false;
                            }
                        }
                        else if (bBody) //语句处理
                        {
                            if (iCurrent == ResolveConfig.Flag && !bFindFlagInBody && !bIntoDouble && iSmallLevel == 0)//@
                            {
                                bFindFlagInBody = true;
                            }
                            else if (iCurrent == ResolveConfig.Flag && iLast == ResolveConfig.Flag && bFindFlagInBody && !bIntoDouble && iSmallLevel == 0) //找到@@，标志无效
                            {
                                bFindFlagInBody = false;
                            }
                            else if (bFindFlagInBody && iCurrent == 32 && !bIntoDouble)//空格
                            {
                                bFindFlagInBody = false;
                            }
                            else if (bFindFlagInBody && iCurrent == 10 && iLast == 13)//回车
                            {
                                bFindFlagInBody = false;
                            }
                            else if (bFindFlagInBody && iCurrent == 34 && !bIntoDouble) //("
                            {
                                bIntoDouble = true;
                            }
                            else if (bFindFlagInBody && iCurrent == 34 && iLast != 92 && bIntoDouble) //\")
                            {
                                bIntoDouble = false;
                            }
                            else if (!bFindFlagInBody && iLast != ResolveConfig.Flag && iCurrent == 123 && !bIntoDouble) //{
                            {
                                iBigLevel++;
                            }
                            else if (!bFindFlagInBody && iLast != ResolveConfig.Flag && iCurrent == 125 && (iLast == 32 || iLast == 10) && iBigLevel > 1) //}
                            {
                                iBigLevel--;
                            }
                            else if (!bFindFlagInBody && iLast != ResolveConfig.Flag && iCurrent == 125 && (iLast == 32 || iLast == 10) && iBigLevel == 1) //}
                            {
                                bProperty = false;
                                bSure = true;
                                flagCode.FlagStyle = FlagStyle.Body;
                                iFlagEnd = iPosition;
                                iBigLevel = 0;
                            }
                        }
                        if (bSure) //确定标志
                        {
                            flagCode.Code = sb.ToString();
                            if (flagCode.FlagStyle == FlagStyle.Property)
                            {
                                if (flagCode.Code.StartsWith(((char)ResolveConfig.Flag) + "Layout=\""))
                                {
                                    flagCode.FlagStyle = FlagStyle.Layout;
                                }
                            }
                            if (flagCode.FlagStyle == FlagStyle.Func)
                            {
                                if (flagCode.Code.StartsWith(((char)ResolveConfig.Flag) + "PlaceHolder(\""))
                                {
                                    flagCode.FlagStyle = FlagStyle.PlaceHolder;
                                }
                            }
                            if (flagCode.FlagStyle == FlagStyle.Body)
                            {
                                flagCode.Code += "\r\n";
                                if (flagCode.Code.StartsWith(((char)ResolveConfig.Flag) + "using{"))
                                {
                                    flagCode.FlagStyle = FlagStyle.Using;
                                }
                                else if (flagCode.Code.StartsWith(((char)ResolveConfig.Flag) + "*{"))
                                {
                                    flagCode.FlagStyle = FlagStyle.Comment;
                                }
                                else if (flagCode.Code.StartsWith(((char)ResolveConfig.Flag) + "PlaceContent(\""))
                                {
                                    flagCode.FlagStyle = FlagStyle.PlaceContent;
                                }
                                else if (flagCode.Code.StartsWith(((char)ResolveConfig.Flag) + "{"))
                                {
                                    flagCode.FlagStyle = FlagStyle.Statement;
                                }
                            }
                            sb.Remove(0, sb.Length);
                            flagCode.Start = iFlagStart;
                            flagCode.End = iFlagEnd;
                            flagCodeInFile.AddCode(flagCode);
                            flagCode = new FlagCode();
                            bFindFlag = false;
                            bSure = false;
                            bProperty = false;
                            bFunc = false;
                            bBody = false;
                        }
                    }
                    iPosition++;
                    iLast = iCurrent;
                    iCurrent = ReadNext();
                }
            }
            catch (Exception ex)
            {
                Dispose();
                throw new Exception(ex.Message);
            }
            Dispose();
            return flagCodeInFile;
        }
        /// <summary>
        /// 初始化文件读取对象
        /// </summary>
        private void InitStringReader()
        {
            if (_stringReader != null)
            {
                _stringReader.Close();
            }
            _stringReader = new StringReader(Source);
        }

        /// <summary>
        /// 读取下一个字符
        /// </summary>
        /// <returns></returns>
        private int ReadNext()
        {
            return _stringReader.Read();
        }

        /// <summary>
        /// 关闭资源
        /// </summary>
        private void Dispose()
        {
            if (_stringReader != null)
            {
                _stringReader.Close();
            }
        }
    }
}
